package com.ajhlp.app.phoneDetailQuery.service;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.annotation.PostConstruct;

import org.apache.commons.io.FileUtils;
import org.apache.log4j.Logger;
import org.springframework.transaction.annotation.Transactional;

import com.ajhlp.app.phoneDetailQuery.db.PhoneRuleDao;
import com.ajhlp.app.phoneDetailQuery.model.PhoneNumRule;
import com.ajhlp.app.phoneDetailQuery.model.PhoneNumRules;
import com.ajhlp.app.phoneDetailQuery.model.RuleOperateFailureException;
import com.thoughtworks.xstream.XStream;

@Transactional
public class PhoneNumRuleCache {
	
	private Logger log = Logger.getLogger(getClass());

	private PhoneRuleDao dao;
	
	public PhoneRuleDao getDao() {
		return dao;
	}

	public void setDao(PhoneRuleDao dao) {
		this.dao = dao;
	}

	private static final Map<String,PhoneNumRule> rules = new ConcurrentHashMap<String, PhoneNumRule>();
	
	private static final String configFileName = "rules.xml";
	
	public void addRule(PhoneNumRule rule) throws RuntimeException{
		if(rule == null || rule.getRule() == null || rule.getRule().equals("")){
			throw new RuleOperateFailureException("规则为空");
		}
		
		if(rules.containsKey(rule.getRule())){
			throw new RuleOperateFailureException("规则已存在");
		}
		
		rules.put(rule.getRule(), rule);
		
		try {
			saveRulesToFile();
		} catch (Exception e) {
			// TODO Auto-generated catch block
			rules.remove(rule.getRule());
			throw new RuleOperateFailureException(e.getMessage());
		}
	} 
	
	public void deleteRule(String rule) throws RuntimeException{
		
		if(!rules.containsKey(rule)){
			throw new RuleOperateFailureException("规则不存在");
		}else{
			
			PhoneNumRule tmp = rules.get(rule);
			
			rules.remove(rule);
			
			try {
				saveRulesToFile();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				rules.put(tmp.getRule(),tmp);
				throw new RuleOperateFailureException(e.getMessage());
			}
		}
	}
	
	public void updateRule(PhoneNumRule rule) throws RuntimeException{
		if(rule == null || rule.getRule() == null || rule.getRule().equals("")){
			throw new RuleOperateFailureException("规则为空");
		}
		
		if(rules.containsKey(rule.getRule())){
			
			int old_price = rules.get(rule.getRule()).getPrice();
			
			String old_comment = rules.get(rule.getRule()).getComment();
			
			rules.get(rule.getRule()).setPrice(rule.getPrice());
			rules.get(rule.getRule()).setComment(rule.getComment());
			
			try {
				saveRulesToFile();
			} catch (Exception e) {
				// TODO Auto-generated catch block
				rules.get(rule.getRule()).setPrice(old_price);
				rules.get(rule.getRule()).setComment(old_comment);
				throw new RuleOperateFailureException(e.getMessage());
			}
		}else{
			addRule(rule);
		}
	}
	
	public Collection<PhoneNumRule> getAllRules(){
		return rules.values();
	}
	
	public List<PhoneNumRule> getOrderListByPrice(String order){
		List<PhoneNumRule> rules = new ArrayList<PhoneNumRule>();
		Iterator<PhoneNumRule> iterator = getAllRules().iterator();
		
		while(iterator.hasNext()){
			rules.add(iterator.next());
		}
		
		Collections.sort(rules);
		
		if("desc".equals(order)){
			Collections.reverse(rules);
		}
		
		return rules;
	}
	
	public PhoneNumRule getRule(String rule){
		return rules.get(rule);
	}
	
	public int getTotalRulesNum(){
		return rules.size();
	}
	
	@PostConstruct
	public void initRulesFromConfigFile(){
		try {
			XStream xStream = new XStream();
			xStream.processAnnotations(PhoneNumRules.class);
			
			PhoneNumRules phoneNumRules = (PhoneNumRules) xStream.fromXML(new File(this.getClass().getClassLoader().getResource(configFileName).getPath()));
			
			rules.clear();
			
			if(phoneNumRules.getRules() == null){
				return;
			}
			
			for(int i=0;i<phoneNumRules.getRules().size();i++){
				rules.put(phoneNumRules.getRules().get(i).getRule(), phoneNumRules.getRules().get(i));
			}
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("初始化号码规则失败", e);
		}
	}
	
	public void saveRulesToFile() throws RuntimeException{
		try {
			PhoneNumRules phoneNumRules = new PhoneNumRules();
			phoneNumRules.setRules(new ArrayList<PhoneNumRule>());
			Iterator<PhoneNumRule> iterator = rules.values().iterator();
			while(iterator.hasNext()){
				phoneNumRules.getRules().add(iterator.next());
			}
			
			XStream xStream = new XStream();
			xStream.processAnnotations(PhoneNumRules.class);
			
			File configFile = new File(this.getClass().getClassLoader().getResource(configFileName).getPath());
			
			FileUtils.write(configFile, xStream.toXML(phoneNumRules), "UTF-8", false);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			log.error("保存号码规则失败", e);
			throw new RuleOperateFailureException("保存号码规则失败");
		}
	}
	
}
